home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / applic / ntp / kent.shar / tosskey.c < prev   
Encoding:
C/C++ Source or Header  |  1991-09-29  |  7.4 KB  |  283 lines

  1. /* modified 6 May 1983 to allow optional command arg which specifies
  2.    output file name. if no arg, output goes to file 'ks' */
  3.  
  4. #include <stdio.h>
  5.  
  6. /* tables to describe permutations, per NBS FIPS */
  7.  
  8. static int pc1c [] =
  9.     { 57, 49, 41, 33, 25, 17, 9,
  10.       1, 58, 50, 42, 34, 26, 18,
  11.       10, 2, 59, 51, 43, 35, 27,
  12.       19, 11, 3, 60, 52, 44, 36 };
  13.  
  14. static int pc1d [] =
  15.     { 63, 55, 47, 39, 31, 23, 15,
  16.       7, 62, 54, 46, 38, 30, 22,
  17.       14, 6, 61, 53, 45, 37, 29,
  18.       21, 13, 5, 28, 20, 12, 4 };
  19.  
  20. static int shiftsked []=
  21.     { 1, 1, 2, 2, 2, 2, 2, 2,
  22.       1, 2, 2, 2, 2, 2, 2, 1 };
  23.  
  24. static int pc2 [] =
  25.     { 14, 17, 11, 24, 1, 5,
  26.       3, 28, 15, 6, 21, 10,
  27.       23, 19, 12, 4, 26, 8,
  28.       16, 7, 27, 20, 13, 2,
  29.       41, 52, 31, 37, 47, 55,
  30.       30, 40, 51, 45, 33, 48,
  31.       44, 49, 39, 56, 34, 53,
  32.       46, 42, 50, 36, 29, 32 };
  33.  
  34. /* --- some bit manipulation primitives --- */
  35.  
  36. /* g_keybit -- extract bit bnum from the key in inkey */
  37. #define g_keybit(bnum) (01 & (inkey [bnum/8] >> (8 - (bnum%8))))
  38.  
  39. long    lrot28 (lval)
  40. /* do left rotate of 28 bit quantity */
  41. long    lval;
  42. {
  43.   lval <<= 1;
  44.   if (0X10000000L & lval) lval++;
  45.   lval &= 0XFFFFFFFL;
  46.   return (lval);
  47. }
  48.  
  49. /* --- following code and data does key schedule generation --- */
  50.  
  51. unsigned skedkeys [16] [4];
  52.  
  53. unsigned inkey [8];     /* input key goes here */
  54.  
  55. long pc2otab [8] [128]; /* table to optimize pc2 */
  56.  
  57. spc2otab ()     /* initialize pc2otab for pc2 lookups */
  58. {
  59. #define NOTSEL  -1
  60.  
  61.   extern long pc2otab [8] [128];
  62.   extern int pc2 [48];
  63.   
  64.   int bn, bv, bitloc, i;
  65.   int bitindx [7];
  66.  
  67.   for (bn = 0; bn < 8; bn++)    /* each input 7-bit byte, l->r */
  68.   {
  69.     for (i = 0; i < 7; i++)     /* find each bit in the byte */
  70.     {
  71.     /* determine where (or if) pc2 places the given bit in the
  72.        output.  set bitindx [0] to the bit number (1->48,l->r)
  73.        where the MSB of the byte occurs, or to NOTSEL if pc2
  74.        doesn't pick it. similar down through bitindx [6]. */
  75.  
  76.       for (bitloc = 0; bitloc < 48; bitloc++)
  77.       {
  78.     /* trying until a match in pc2 found or table exhausted */
  79.         if (pc2 [bitloc] == (1 + ((bn * 7) + i)))
  80.         {
  81.           bitindx [i] = bitloc + 1;
  82.           break;
  83.         } 
  84.       }
  85.       if (bitloc == 48) bitindx [i] = NOTSEL;
  86.     }
  87.  
  88.     for (bv = 0; bv < 128; bv++)
  89.     {
  90.       /* setting up a table entry for each input byte value */
  91.       pc2otab [bn] [bv] = 0L;
  92.       if (bn < 4)       /* this is left word (nbs bits 1-24) */
  93.       {
  94.     for (i = 0; i < 7; i++)
  95.     {
  96.        if (NOTSEL == bitindx [i]) continue;
  97.         if (bv & (01 << (6 - i)))
  98.           pc2otab [bn] [bv] |= (0X1L << (24 - bitindx [i]));
  99.     }
  100.       }
  101.       else              /* this is right word (nbs bits 25-48) */
  102.       {
  103.     for (i = 0; i < 7; i++)
  104.     {
  105.           if (NOTSEL == bitindx [i]) continue;
  106.            if (bv & (01 << (6 - i)))
  107.              pc2otab [bn] [bv] |= (0X1L << (48 - bitindx [i]));
  108.     }
  109.       }
  110.     }
  111.   }
  112. }
  113.  
  114. ksmake ()       /* Make a key schedule from key bytes in inkey */
  115. {
  116.   extern unsigned skedkeys [16] [4];
  117.   extern long pc2otab [8] [128];
  118.  
  119.   int   round;
  120.   long  pcct, pcdt;
  121.   long  pc2out [2];
  122.   int   i;
  123.  
  124.   /* do pc-1 permutation, extracting bits from inkey */
  125.   pcct = pcdt = 0L;
  126.   for (i = 0; i < 27; i++)   
  127.    /* filling all appropriate bits */
  128.   {
  129.     pcct |= g_keybit(pc1c [i]);
  130.     pcdt |= g_keybit(pc1d [i]);
  131.     pcct <<= 1;
  132.     pcdt <<= 1;
  133.   }
  134.   /* one final ior, without a shift */
  135.   pcct |= g_keybit(pc1c [i]);
  136.   pcdt |= g_keybit(pc1d [i]);
  137.  
  138.   for (round = 0; round < 16; round++)
  139.   {
  140.     /* always at least one shift */
  141.     pcct = lrot28 (pcct);
  142.     pcdt = lrot28 (pcdt);
  143.  
  144.     if (shiftsked [round] == 2)
  145.     {   /* this round needs another shift */
  146.       pcct = lrot28 (pcct);
  147.       pcdt = lrot28 (pcdt);
  148.     } 
  149.  
  150.     /* Now, pcct and pcdt have the values on which we can apply
  151.        pc2 and select the key bits, storing them in pc2out[0] and
  152.        pc2out[1]. The high order [pc2out[0]] bits all come from
  153.        pcct, and the low order from pcdt. */
  154.  
  155.     pc2out [0] = pc2otab [0] [pcct >> 21];
  156.     pc2out [0] |= pc2otab [1] [0X7F & (pcct >> 14)];
  157.     pc2out [0] |= pc2otab [2] [0X7F & (pcct >> 7)];
  158.     pc2out [0] |= pc2otab [3] [0X7F & pcct];
  159.  
  160.     pc2out [1] = pc2otab [4] [pcdt >> 21];
  161.     pc2out [1] |= pc2otab [5] [0X7F & (pcdt >> 14)];
  162.     pc2out [1] |= pc2otab [6] [0X7F & (pcdt >> 7)];
  163.     pc2out [1] |= pc2otab [7] [0X7F & pcdt];
  164.  
  165.     /* order key bits and bytes so as to be compatible with
  166.        the format generated by the E implementation */
  167.  
  168.     skedkeys [round] [0] = 0XFC00 & (pc2out [0] >> 8);
  169.     skedkeys [round] [0] |= (0XFC & (pc2out [0] >> 4));
  170.     skedkeys [round] [1] = 0XFC00 & (pc2out [1] >> 8);
  171.     skedkeys [round] [1] |= (0XFC & (pc2out [1] >> 4));
  172.  
  173.     skedkeys [round] [2] = 0XFC00 & (pc2out [0] >> 2);
  174.     skedkeys [round] [2] |= (0XFC & (pc2out [0] << 2));
  175.     skedkeys [round] [3] = 0XFC00 & (pc2out [1] >> 2);
  176.     skedkeys [round] [3] |= (0XFC & (pc2out [1] << 2));
  177.   }
  178. }
  179.  
  180. int parval ()  /* test parity of key in inkey; return 1 iff OK */
  181. {
  182.   int i, j;
  183.   int parac;
  184.   unsigned incopy;
  185.  
  186.   for (i = 0; i < 8; i++)       /* do each byte */
  187.   {
  188.     parac = 0;
  189.     incopy = inkey [i];
  190.  
  191.     for (j = 0; j < 8; j++)     /* 8 bits in a DES byte */
  192.     {
  193.       if (incopy & 01) parac++;
  194.       incopy >>= 1;
  195.     }
  196.     if (! (parac & 01)) return (0); /* no odd parity on this byte */
  197.   }
  198.   return (1);   /* OK on all of them */
  199. }
  200.  
  201. int tossbit ()      /* request and return a coin toss value */
  202. {
  203.   char inarr [10];
  204.  
  205.   for (;;)      /* infinite loop until acceptable result entered */
  206.   {
  207.     printf ("heads or tails? (h or t): ");
  208.     scanf ("%s", inarr);
  209.     if ((inarr [0] == 'h') || (inarr [0] == 'H')) return (1);
  210.     if ((inarr [0] == 't') || (inarr [0] == 'T')) return (0);
  211.     printf ("Input unacceptable! Enter 'h' or 't'\n");
  212.   }
  213. }
  214. coin_to_key ()  /* prompt for and accept coin tosses, build inkey */
  215. {
  216.   extern unsigned inkey [8];
  217.  
  218.   int kbyte, kbit, parchk, toss, tosstot;
  219.  
  220.   tosstot = 0;
  221.   for (kbyte = 0; kbyte < 8; kbyte++)
  222.   {
  223.     inkey [kbyte] = 0;
  224.     parchk = 0;                         /* parity accumulator */
  225.     for (kbit = 0; kbit < 7; kbit++)    /* get 7 real bits for byte */
  226.     {
  227.       toss = tossbit ();
  228.       inkey [kbyte] |= (01 << (7 - kbit)) * toss;
  229.       parchk += toss;
  230.       tosstot += toss;  /* keep track of how many ones */
  231.     }
  232.     inkey [kbyte] |= 01 * (0 == (parchk & 01));
  233.     printf ("key byte %d (parity adjusted) is %x\n", kbyte+1, inkey [kbyte]);
  234.   }
  235.   printf ("Entire key is: ");
  236.   for (kbyte = 0; kbyte < 8; kbyte++) printf ("%x ", inkey [kbyte]);
  237.   printf ("\n");
  238.   printf ("Of 56 tossed bits, %d were ones\n", tosstot);
  239. }
  240.  
  241. /* main for tosskey -- accept and validate key, output schedule */
  242. main (argc, argv)
  243. int     argc;
  244. char    *argv [];
  245. {
  246.   extern unsigned skedkeys [16] [4];
  247.  
  248.   int i, j;
  249.   FILE * fp, *fopen ();
  250.  
  251.   spc2otab ();
  252.  
  253.   printf ("Welcome to tosskey. Prepare your coin for use.\n");
  254.  
  255.   coin_to_key ();       /* get individual entries, compose inkey */
  256.  
  257.   if (! parval ())
  258.   {
  259.     printf ("Bad parity on key... aborting...\n");
  260.     exit (1);
  261.   }
  262.  
  263.   printf ("Computing key schedule...\n");
  264.   ksmake ();
  265.  
  266.   if (NULL == (fp = fopen (((argc > 1) ? argv [1] : "ks"), "w")))
  267.   {
  268.     printf ("tosskey -- can't open output file '%s'",
  269.      ((argc > 1) ? argv [1] : "ks"));
  270.     exit (1);
  271.   }
  272.   
  273.   for (i = 0; i < 16; i++)      /* output entire schedule to file */
  274.   {
  275.     for (j = 0; j < 4; j++)
  276.      /* output format is xxxxxx00xxxxxx00 */
  277.      fprintf (fp, "%x\n", skedkeys [i] [j]);
  278.   }
  279.   
  280.   printf ("tosskey -- key schedule output to file '%s'\n",
  281.    ((argc > 1) ? argv [1] : "ks"));
  282. }
  283.